package com.bsj.travel.monitor.service.impl;

import com.bsj.travel.cached.redis.RedisCached;
import com.bsj.travel.constant.NumericalConstants;
import com.bsj.travel.constant.SecurityConstants;
import com.bsj.travel.constant.TdEngineDataConstants;
import com.bsj.travel.constants.RedisConstant;
import com.bsj.travel.def.common.DO.ProductDO;
import com.bsj.travel.def.common.DTO.tdengine.TDCountDto;
import com.bsj.travel.def.common.DTO.web.TimeDTO;
import com.bsj.travel.def.common.VO.device.DeviceTotalVO;
import com.bsj.travel.def.global.JsonResult;
import com.bsj.travel.def.global.JsonResultEnum;
import com.bsj.travel.device.RemoteProductService;
import com.bsj.travel.exception.ApiException;
import com.bsj.travel.mapper.tdengine.TableTDengineMapper;
import com.bsj.travel.monitor.service.MonitorService;
import com.bsj.travel.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/***
 * @description MonitorServiceImpl
 * @author LiJiaXin
 * @version 1.0.0
 * @time 2024/1/30 11:15
 **/
@Slf4j
@Service
public class MonitorServiceImpl implements MonitorService {

    @Autowired
    private RedisCached redisCached;

    @Resource
    private RemoteProductService remoteProductService;

    @Resource
    private TableTDengineMapper tableTDengineMapper;

    /**
     * 实时监控
     *
     * @param timeDTO
     * @return com.bsj.travel.def.global.JsonResult<java.util.Map < java.lang.String, java.util.List < com.bsj.travel.def.common.VO.device.DeviceTotalVO>>>
     * @author ljx
     * @time 2024/1/30 11:41
     */
    @Override
    public JsonResult<Map<String, List<DeviceTotalVO>>> realTimeMonitor(TimeDTO timeDTO) {
        JsonResult<List<ProductDO>> jsonResult = remoteProductService.list(NumericalConstants.TWO, SecurityConstants.INNER);
        List<ProductDO> productDOS = jsonResult.getData();
        if (CollectionUtils.isEmpty(productDOS)) {
            throw new ApiException(JsonResultEnum.PRODUCT_IS_NOT_EXIST);
        }
        String startTime = timeDTO.getStartTime();
        String endTime = timeDTO.getEndTime();
        Long start = getTimestamp(startTime);
        Long end = getTimestamp(endTime);
        Map<Long, DeviceTotalVO> onLineNumMap = new HashMap<>();
        List<DeviceTotalVO> devToPlaNum = null;
        List<DeviceTotalVO> plaToDevNum = null;
        for (ProductDO productDO : productDOS) {
            String productKey = productDO.getProductKey();
            //获取所有产品对应的设备数量
            Map<String, String> onLineMap = redisCached.hgetAll(RedisConstant.CLIENT_CONNECT_SUM_KEY + productKey);
            if (!CollectionUtils.isEmpty(onLineMap)) {
                Iterator<Map.Entry<String, String>> iterator = onLineMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, String> entry = iterator.next();
                    long key = Long.parseLong(entry.getKey());
                    //筛选出时间区间内的数据
                    if (key >= start && key <= end) {
                        DeviceTotalVO deviceTotalVO = onLineNumMap.get(key);
                        if (deviceTotalVO == null) {
                            deviceTotalVO = new DeviceTotalVO(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM, new Date(key)), 0L);
                        }
                        deviceTotalVO.setTotal(deviceTotalVO.getTotal() + Long.parseLong(entry.getValue()));
                        onLineNumMap.put(key, deviceTotalVO);
                    }
                }
            }
            //设备到云端消息
            TDCountDto tdCountDto = new TDCountDto(TdEngineDataConstants.T_LOG + productKey, startTime, endTime, NumericalConstants.ZERO);
            devToPlaNum = tableTDengineMapper.selectDataCount(tdCountDto);
            //云端到设备消息
            tdCountDto.setServeType(NumericalConstants.ONE);
            plaToDevNum = tableTDengineMapper.selectDataCount(tdCountDto);
        }
        List<DeviceTotalVO> onLineNum = onLineNumMap.entrySet().stream().map(Map.Entry::getValue).distinct()
                .sorted(Comparator.comparing(DeviceTotalVO::getNewTime)).collect(Collectors.toList());
        return JsonResult.success(Map.of("onLineNum", onLineNum, "devToPlaNum", devToPlaNum, "plaToDevNum", plaToDevNum));
    }

    /**
     * 获取时间戳
     *
     * @param time
     * @return void
     * @author ljx
     * @time 2024/1/30 15:30
     */
    private Long getTimestamp(String time) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS);
        LocalDateTime date = LocalDateTime.parse(time, formatter);
        Instant instant = date.atZone(ZoneId.systemDefault()).toInstant();
        long timestamp = instant.toEpochMilli();
        return timestamp;
    }

}
